<script setup lang="ts">
import { withDefaults, defineProps, defineEmits, ref, nextTick } from 'vue';

const input = ref('')
// 定义 props
const props = withDefaults(defineProps<{
    placeholder?: string;
    type?: string;
    modelValue?: string;
    precision?: number;
    myType?: string;
}>(), {
    placeholder: '请输入内容',
    type: 'text',
    modelValue: '',
    myType: '',
    precision: 2
});

// 显式声明支持的事件类型（包括原生input事件）
const emit = defineEmits<{
    (e: 'update:modelValue', value: string): void;
    (e: 'input', event: Event): void;
    (e: 'focus', event: FocusEvent): void;
    (e: 'blur', event: FocusEvent): void;
    (e: 'change', event: Event): void;
    (e: 'keydown', event: KeyboardEvent): void;
    (e: 'keyup', event: KeyboardEvent): void;
}>();
const onKeydown = (e: KeyboardEvent) => {
    const target = e.target as HTMLInputElement;
    const { myType, precision = 2 } = props; // 默认为2位小数，可通过props控制

    // 非number类型直接返回，不做限制
    if (myType !== 'number') return;

    // 允许Ctrl+常用快捷键（复制、粘贴、全选、剪切）
    if (e.ctrlKey && ['v', 'V', 'a', 'A', 'c', 'C', 'x', 'X'].includes(e.key)) {
        return;
    }

    // 允许的功能键和输入键（提前定义，清晰明了）
    const allowedKeys = ['Backspace', 'ArrowRight', 'ArrowLeft', '.'];
    const isNumberKey = /^[0-9]$/.test(e.key); // 数字键判断

    // 非允许的键直接阻止
    if (!isNumberKey && !allowedKeys.includes(e.key)) {
        e.preventDefault();
        return;
    }

    // 处理小数点：已有小数点则阻止，且小数点前必须有数字
    if (e.key === '.') {
        // 已有小数点 → 阻止
        if (target.value.includes('.')) {
            e.preventDefault();
            return;
        }
        // 小数点前无数字 → 阻止（确保小数点前必须有数字）
        if (!target.value) {
            e.preventDefault();
            return;
        }
    }

    // 处理数字键：避免开头连续0（如"00"）
    if (isNumberKey) {
        // 若当前值为"0"，输入数字则替换（避免"0123"）
        if (target.value === '0') {
            target.value = e.key;
            e.preventDefault(); // 阻止默认输入，用我们设置的值
        }
    }

    // 处理小数位数限制（仅当有小数点时生效）
    const [, decimalPart] = target.value.split('.');
    const decimalLength = decimalPart?.length || 0;
    const cursorDistanceToEnd = target.value.length - (target.selectionEnd || target.value.length);

    // 小数位数超过精度且不在删除/移动光标时 → 阻止输入
    if (
        decimalLength >= precision &&
        e.key !== 'Backspace' &&
        !['ArrowRight', 'ArrowLeft'].includes(e.key) &&
        cursorDistanceToEnd < precision
    ) {
        e.preventDefault();
    }

    // 延迟处理粘贴/输入后的格式修正（过滤非数字和小数点）
    setTimeout(() => {
        const currentValue = target.value;
        // 1. 只保留数字和小数点
        let filtered = currentValue.replace(/[^0-9.]/g, '');
        // 2. 确保最多一个小数点
        filtered = filtered.replace(/(\.)(?=.*\.)/g, '');
        // 3. 修复小数点前无数字的情况（如".123" → "0.123"）
        if (filtered.startsWith('.')) {
            filtered = '0' + filtered;
        }
        // 4. 避免开头连续0（如"000123" → "0123"已通过前面处理，这里进一步确保）
        if (/^0+[1-9]/.test(filtered)) {
            filtered = filtered.replace(/^0+/, '');
        }
        target.value = filtered;
    }, 50);
}
const inputFn = (e: Event) => {
    emit('update:modelValue', (e.target as HTMLInputElement)?.value ?? '');
    emit('input', e);
}
const handlePaste = (e: ClipboardEvent) => {
    const { myType, precision = 2 } = props;
    if (myType !== 'number') return;

    e.preventDefault(); // 阻止默认粘贴，手动处理内容

    const target = e.target as HTMLInputElement;
    // 获取粘贴的文本
    const pastedText = e.clipboardData?.getData('text') || '';

    // 1. 过滤非数字和小数点
    let filtered = pastedText.replace(/[^0-9.]/g, '');
    // 2. 只保留第一个小数点
    filtered = filtered.replace(/(\.)(?=.*\.)/g, '');
    // 3. 修正小数点前无数字的情况（如".123" → "0.123"）
    if (filtered.startsWith('.')) {
        filtered = '0' + filtered;
    }
    // 4. 去除开头多余的0（如"00123" → "123"，"000.45" → "0.45"）
    filtered = filtered.replace(/^0+([1-9])/, '$1'); // 整数部分开头多0处理
    filtered = filtered.replace(/^0+\./, '0.'); // 小数开头多0处理（如"000.45" → "0.45"）

    // 5. 限制小数位数
    const [integerPart, decimalPart] = filtered.split('.');
    if (decimalPart && decimalPart.length > precision) {
        filtered = `${integerPart}.${decimalPart.slice(0, precision)}`;
    }

    // 6. 替换当前输入框内容（保留光标位置）
    const cursorPos = target.selectionStart || 0;
    const currentValue = target.value;
    // 拼接：光标前内容 + 过滤后的粘贴内容 + 光标后内容
    const newValue = currentValue.slice(0, cursorPos) + filtered + currentValue.slice(target.selectionEnd || 0);
    target.value = newValue;

    // 7. 调整光标位置到粘贴内容末尾
    target.selectionStart = cursorPos + filtered.length;
    target.selectionEnd = cursorPos + filtered.length;
};
const compositionstartFn = (e: Event) => {
}
const compositionend = (e: CompositionEvent) => {
    if (!props.myType) return
    const target = e.target as HTMLInputElement
    target.value = target.value.replace(e.data, "")
}

</script>

<template>
    <input ref="input" @compositionstart="compositionstartFn" @compositionend="compositionend"
        class="px-[10px] box-border placeholder:tracking-[0px] dark:placeholder:text-[#707a8a] dark:text-[#EAECEF] bg-white dark:border-[#474D57] dark:bg-dark-bg  h-[46px] text-[16px] caret-primary-500 dark:focus:border-primary-500 placeholder:text-[#999]  border-[1px] border-solid border-[#ddd] rounded-[10px]  sm:hover:!border-primary-500 w-[100%] focus:outline-none focus:border-primary-500 sm:active:border-primary-500"
        :value="props.modelValue" @input="inputFn" @focus="$emit('focus', $event)" @blur="$emit('blur', $event)"
        @change="$emit('change', $event)" @paste="handlePaste" @keydown="onKeydown" @keyup="$emit('keyup', $event)"
        :placeholder="placeholder" :type="type" />
</template>

<style scoped></style>